package com.sls.game.service.impl;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.sls.core.common.CommonUtil;
import com.sls.core.http.HttpClient;
import com.sls.core.socket.Head;
import com.sls.core.socket.ServerDisponseException;
import com.sls.core.util.ServerDateAndTime;
import com.sls.core.util.UtilMD5Encryption;
import com.sls.game.assist.Helper;
import com.sls.game.common.DeductionRefund;
import com.sls.game.constant.ExceptionCodeDes;
import com.sls.game.dao.DownstreamUserDAO;
import com.sls.game.dao.GoodsOrderDAO;
import com.sls.game.dao.GoodsOrderLogDAO;
import com.sls.game.parser.sls.OrderStatusSendParse;
import com.sls.game.pojo.DeductionRefundInfo;
import com.sls.game.pojo.DownstreamUserInfo;
import com.sls.game.pojo.GoodsOrderInfo;
import com.sls.game.pojo.GoodsOrderLog;
import com.sls.game.pojo.SLSHttpInterfaceInfo;
import com.sls.game.pojo.enlink.EnLinkAsyncRequestInfo;
import com.sls.game.service.EnLinkAsyncReturnService;

/**
 * 恩联异步返回实现类
 * 
 * @author cx
 * 
 */
@Service("enLinkAsyncReturnService")
public class EnLinkAsyncReturnServiceImpl implements EnLinkAsyncReturnService {

	private static Logger log = Logger
			.getLogger(EnLinkAsyncReturnServiceImpl.class);

	private Gson gson = null;

	@Resource(name = "goodsOrderDAO")
	private GoodsOrderDAO goodsOrderDAO;
	@Resource(name = "goodsOrderLogDAO")
	private GoodsOrderLogDAO goodsOrderLogDAO;

	private DownstreamUserDAO downstreamUserDAO;

	public DownstreamUserDAO getDownstreamUserDAO() {
		return downstreamUserDAO;
	}

	@Resource(name = "downstreamUserDAO")
	public void setDownstreamUserDAO(DownstreamUserDAO downstreamUserDAO) {
		this.downstreamUserDAO = downstreamUserDAO;
	}

	public EnLinkAsyncReturnServiceImpl() {
		gson = CommonUtil.gson();
	}

	/**
	 * 订单结果异步通知
	 * 
	 * @param body
	 * @param head
	 */
	@Override
	public String updateOrderStatus(String body, Head head)
			throws ServerDisponseException {
		EnLinkAsyncRequestInfo asyncInfo = gson.fromJson(body,
				EnLinkAsyncRequestInfo.class);
		boolean flag = this.checkData(asyncInfo);
		if (flag) {
			// 主动通知下游用户
			String userhandleResult = sendNotifyToDownUserMsg(asyncInfo, head);

			updateGoodsOrder(head, asyncInfo, userhandleResult);
		}
		return null;
	}

	/**
	 * 主动通知下游用户
	 * 
	 * @param asyncInfo
	 */
	private String sendNotifyToDownUserMsg(EnLinkAsyncRequestInfo asyncInfo,
			Head head) {
		String handleResult = "FAILED";
		String orderId = asyncInfo.getForginOrderNo();
		GoodsOrderInfo orderInfo = this.goodsOrderDAO.queryByOrderId(orderId);
		String notifyUrl = "";
		// 下游用户编号
		String contractId = null;
		if (orderInfo != null) {
			notifyUrl = orderInfo.getNotifyUrl();
			contractId = orderInfo.getContractId();

			String secretKey = null; // 下游用户密钥
			DownstreamUserInfo downstreamUserInfo = null;
			downstreamUserInfo = downstreamUserDAO
					.queryUserByUserNO(contractId);
			if (downstreamUserInfo != null) {
				secretKey = downstreamUserInfo.getSecretKey();
			}

			String httpUrl = notifyUrl + "?"
					+ this.assembleParameter(asyncInfo, orderInfo, secretKey);

			HttpClient httpClient = new HttpClient();
			// 供应商返回消息编码方式
			String supplyEncode = "UTF-8";
			// 给下游发消息
			String xmlStr = "";
			try {
				log.info("请求ID："+head.getRequestId()+"，异步回调给下游用户的url：" + httpUrl);
				xmlStr = httpClient.doGet(httpUrl, supplyEncode);
				log.info("请求ID：" + head.getRequestId() + "，下游用户的返回结果：" + xmlStr);
			} catch (Exception e) {
				log.error("请求ID：" + head.getRequestId() + "，主动通知下游用户出现异常！", e);
			}

			if (xmlStr != null && !("".equals(xmlStr))) {
				SLSHttpInterfaceInfo slsInfo = null;
				slsInfo = OrderStatusSendParse.readUserSendMsg(xmlStr);
				if (slsInfo != null) {
					handleResult = slsInfo.getHandleResult();
				}
			}
		}

		return handleResult;
	}

	/**
	 * 拼接要发送的url
	 * 
	 * @param asyncInfo
	 * @param goodsOrderInfo
	 * @return
	 */
	private String assembleParameter(EnLinkAsyncRequestInfo asyncInfo,
			GoodsOrderInfo goodsOrderInfo, String secretKey) {
		// 下游用户订单号
		String ptOrderNo = goodsOrderInfo.getMerchantOrderId();
		// 手拉手订单号
		String supOrderNo = asyncInfo.getForginOrderNo();
		// 充值后状态
		String orderState = asyncInfo.getResultCode();
		// 成功处理时间
		String ordersuccesstime = ServerDateAndTime.getNowDateTime();
		// 失败原因
		String err_msg = asyncInfo.getRemark();

//		String logCodmsg = null;
//		if ("000000".equals(orderState)) { // 成功
//			logCodmsg = "成功";
//		} else if ("999999".equals(orderState)) { // 失败
//			logCodmsg = "失败";
//		}
//		log.info("恩联异步推送过来的订单处理结果：  \n手拉手订单号:" + supOrderNo + "充值后状态:"
//				+ logCodmsg + "处理时间:" + ordersuccesstime + "失败原因:" + err_msg);


		StringBuilder strBui = new StringBuilder();
		strBui.append("ptOrderNo=");
		strBui.append(ptOrderNo);
		strBui.append("&");
		strBui.append("supOrderNo=");
		strBui.append(supOrderNo);
		strBui.append("&");
		strBui.append("status=");
		String status = null;
		if ("000000".equals(orderState)) { // 成功
			status = "ORDER_SUCCESS";
			err_msg = ""; // ----------成功了为空
		} else if ("999999".equals(orderState)) { // 失败
			status = "ORDER_FAILED";
			err_msg = "208"; // ---------失败
		}
		strBui.append(status);
		strBui.append("&");

		if ("ORDER_SUCCESS".equals(status)) { // ---------订单成功，才传成功充值时间
			strBui.append("supOrderSuccessTime=");
			strBui.append(ordersuccesstime);
			strBui.append("&");
		} else { // ---------------------订单失败时，才传错误码
			strBui.append("failedReason=");
			if (StringUtils.isNotBlank(err_msg)) {
				try {
					err_msg = URLEncoder.encode(err_msg, "UTF-8");
				} catch (UnsupportedEncodingException e) {
					log.error("编码异常", e);
				}
			}
			strBui.append(err_msg);
			strBui.append("&");
		}

		strBui.append("sign=");
		String sign = createSign(ptOrderNo, supOrderNo, status,
				ordersuccesstime, err_msg, secretKey);
		strBui.append(sign);
		log.info("异步发送给下游用户的订单处理结果    \n 合作方订单编号:" + ptOrderNo + "\n 本地订单编号:"
				+ supOrderNo + "\n 订单最终处理结果：" + status + "\n订单处理的时间:"
				+ ordersuccesstime + "\n失败原因：" + err_msg);

		String result = strBui.toString().trim();
		return result;
	}

	/**
	 * 签名字符串
	 * 
	 * @param ptOrderNo
	 * @param supOrderNo
	 * @param status
	 * @param supOrderSuccessTime
	 * @param err_msg
	 * @return
	 */
	private String createSign(String ptOrderNo, String supOrderNo,
			String status, String supOrderSuccessTime, String err_msg,
			String secretKey) {
		StringBuilder strBui = new StringBuilder();
		strBui.append(ptOrderNo);
		strBui.append(supOrderNo);
		strBui.append(status);
		if (supOrderSuccessTime != null && !("".equals(supOrderSuccessTime))) {
			strBui.append(supOrderSuccessTime);
		}
		if (err_msg != null && !("".equals(err_msg))) {
			strBui.append(err_msg);
		}

		strBui.append(secretKey);
		String data = strBui.toString().trim();
		String result = null;
		result = UtilMD5Encryption.createMD5Encryption(data);

		return result;
	}

	/**
	 * 根据交易返回的结果更新订单表
	 * 
	 * @param head
	 * 
	 * @param info
	 * 
	 */
	private void updateGoodsOrder(Head head, EnLinkAsyncRequestInfo info,
			String userhandleResult) {

		// sls订单编号
		String orderNo = info.getForginOrderNo();
		// SUP平台订单号
		String supOrderNo = info.getTranaNo();
		// 订单交易状态
		String statusCode = info.getResultCode();
		// SUP平台充值成功时间
		String supOrderSuccessTime = info.getTime();

		GoodsOrderInfo goodsOrderInfo = new GoodsOrderInfo();
		goodsOrderInfo.setOrderId(orderNo);
		goodsOrderInfo.setSupOrderId(supOrderNo);
		// goodsOrderInfo.setResult(statusCode);

		String status = "1";
		if ("000000".equals(statusCode)) { // 成功
			status = "1";
		} else if ("999999".equals(statusCode)) { // 失败
			status = "0";

			// 退款操作
			DeductionRefundInfo dedInfo = null;
			dedInfo = DeductionRefund.refundWhenAsynCallBackFailed(orderNo,
					goodsOrderDAO, head);
			String paymentStatus = "";
			if (dedInfo != null) {
				paymentStatus = dedInfo.getPaymentStatus();
			}

			if ("1".equals(paymentStatus)) { // 成功
				goodsOrderInfo.setIsPay("3"); // 退款成功

				// 退款成功，通知下游用户
				DeductionRefund.noticeUserRefundMsg(orderNo, dedInfo,
						goodsOrderDAO, downstreamUserDAO, goodsOrderLogDAO);

			} else if ("2".equals(paymentStatus)) {
				GoodsOrderInfo orderInfo = goodsOrderDAO
						.queryByOrderId(orderNo);
				if (orderInfo != null) {
					String isPayValue = orderInfo.getIsPay(); // 支付状态值
					if ("1".equals(isPayValue)) {
						goodsOrderInfo.setIsPay("2"); // 退款失败
					}
				}
			}
		}
		goodsOrderInfo.setStatus(status);

		goodsOrderInfo.setSupOrderSuccessTime(supOrderSuccessTime);
		goodsOrderInfo.setUserhandleResult(userhandleResult);
		goodsOrderInfo.setSynOrAsy("1"); // 异步推送
		// 数据更新
		try {
			goodsOrderDAO.update(goodsOrderInfo);
		} catch (Exception e) {
			log.error(e);
			throw new ServerDisponseException(
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getCode(),
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getDescription());
		}

		// 写订单日志
		try {
			String orderId = orderNo;
			GoodsOrderInfo goodsOrderInfo1 = new GoodsOrderInfo();
			goodsOrderInfo1 = this.goodsOrderDAO.queryByOrderId(orderId);
			if (goodsOrderInfo1 != null) {
				GoodsOrderLog orderLog = Helper.copy(goodsOrderInfo1);
				orderLog.setId(UUID.randomUUID().toString());
				orderLog.setModifyTime(ServerDateAndTime
						.getNowDateTimeOfFormat());
				this.goodsOrderLogDAO.insert(orderLog);
			}

		} catch (Exception e) {
			log.error(e);
			throw new ServerDisponseException(
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getCode(),
					ExceptionCodeDes.ACCESS_DATABASE_ERROR.getDescription());
		}
	}

	/**
	 * 数据校验
	 * 
	 * @param enLinkInfo
	 * @param resp
	 * @return
	 * @throws IOException
	 */
	private boolean checkData(EnLinkAsyncRequestInfo enLinkInfo) {
		boolean flag = false;
		if (StringUtils.isEmpty(enLinkInfo.getTranaNo())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.COOPERATION_PLATFORM_ORDERNO_NULL
							.getCode(),
					ExceptionCodeDes.COOPERATION_PLATFORM_ORDERNO_NULL
							.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getForginOrderNo())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.SLS_ORDERNO_NULL.getCode(),
					ExceptionCodeDes.SLS_ORDERNO_NULL.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getProdCode())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.PRODCODE_EMPTY.getCode(),
					ExceptionCodeDes.PRODCODE_EMPTY.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getProdName())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.EN_LINK_PRODNAME_EMPTY.getCode(),
					ExceptionCodeDes.EN_LINK_PRODNAME_EMPTY.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getProdNum())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.EN_LINK_PRODNUM_EMPTY.getCode(),
					ExceptionCodeDes.EN_LINK_PRODNUM_EMPTY.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getTime())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.EN_LINK_TIME_EMPTY.getCode(),
					ExceptionCodeDes.EN_LINK_TIME_EMPTY.getDescription());
		} else if (StringUtils.isEmpty(enLinkInfo.getResultCode())) {
			throw new ServerDisponseException(
					ExceptionCodeDes.EN_LINK_RESULTCODE_EMPTY.getCode(),
					ExceptionCodeDes.EN_LINK_RESULTCODE_EMPTY.getDescription());
		} else {
			flag = true;
		}
		return flag;
	}
}
